#include "bilbao/led/LedController.h"

#define LED01(K,V) if ((leds | 0x1F) == 0x3F) K = V
#define LED02(K,V) if ((leds | 0x2F) == 0x3F) K = V
#define LED03(K,V) if ((leds | 0x37) == 0x3F) K = V
#define LED04(K,V) if ((leds | 0x3B) == 0x3F) K = V
#define LED05(K,V) if ((leds | 0x3D) == 0x3F) K = V
#define LED06(K,V) if ((leds | 0x3E) == 0x3F) K = V

namespace bilbao
{
	namespace led
	{
		//--------------------------------------------------------------------------------
		LedController* LedController::_instance = NULL;
		//--------------------------------------------------------------------------------
		LedController::LedController(void)
		{
			//NOTE: Isso deveria estar na inicialização do sistema SAT.
//#ifdef BILBAO_AMR9
			//system("rm -rf /dev/avila_led");
			//system("mknod /dev/avila_led c 197 1");
//#endif

			memset( estado_leds, 0, sizeof(estado_leds) );
//#ifdef BILBAO_AMR9
			fd = open( "/dev/avila_led", O_WRONLY );
//#endif
			//pthread_create( &thread, NULL, Led::run, (void*)this );
			pthread_mutex_init( &mutex, NULL );

			setPriority( lang::Thread::PRIORITY_MAX );
			start();
		}
		//--------------------------------------------------------------------------------
		LedController::~LedController(void)
		{
			finalize();
		}
		//--------------------------------------------------------------------------------
		LedController* LedController::getInstance( void )
		{
			if ( !_instance )
			{
				_instance = new LedController();
			}

			return _instance;
		}
		//--------------------------------------------------------------------------------
		void LedController::run(void)
		{
			int code;
			char c;
			int i=0;

			while(true)
			{
				code = 0;

			    pthread_mutex_lock( &mutex );

			    //MSG( "run... lock\n" );

			    for(int i=0, j=1; i<6; i++, j*=2)
			    {
			    	if( estado_leds[i] == E_TURN_ON ) code += j;
			        else if( estado_leds[i] == (E_TURN_BLINK + E_TURN_ON) )
			        {
			        	estado_leds[i] = E_TURN_BLINK;
			        }
			        else if( estado_leds[i] == (E_TURN_BLINK) )
			        {
			        	code += j;
			        	estado_leds[i] = E_TURN_BLINK + E_TURN_ON;
			        }
			    }

			    //print();

			    c = ~(code & 0xFF);

			    write( fd, &c, 1 );
			    fsync( fd );

			    //MSG( "run... unlock\n" );

			    pthread_mutex_unlock( &mutex );
			    usleep(365000);
			}
		}
		//--------------------------------------------------------------------------------
		void LedController::turnOn( int leds )
		{
			if( fd )
			{
				pthread_mutex_lock( &mutex );
				setStateLeds( leds, E_TURN_ON );
			    pthread_mutex_unlock( &mutex );
			}
		}
		//--------------------------------------------------------------------------------
		void LedController::turnOff( int leds )
		{
			if ( fd )
			{
				pthread_mutex_lock( &mutex );
				setStateLeds( leds, E_TURN_OFF );
				pthread_mutex_unlock( &mutex );
			}
		}
		//--------------------------------------------------------------------------------
		void LedController::blink( int leds )
		{
			if ( fd )
			{
				pthread_mutex_lock( &mutex );
				setStateLeds( leds, E_TURN_BLINK );
				pthread_mutex_unlock( &mutex );
			}
		}
		//--------------------------------------------------------------------------------
		void LedController::print(void)
		{
			//TODO: LOG
			//LOG();
		}
		//--------------------------------------------------------------------------------
		void LedController::finalize(void)
		{
			if ( fd ) close(fd);
		}
		//--------------------------------------------------------------------------------
		// Private
		//--------------------------------------------------------------------------------
		void LedController::setStateLeds( int leds, E_LEDSTATE state )
		{
			//
			LED01(estado_leds[0], state);
			LED02(estado_leds[1], state);
			LED03(estado_leds[2], state);
			LED04(estado_leds[3], state);
			LED05(estado_leds[4], state);
			LED06(estado_leds[5], state);
		}
		//--------------------------------------------------------------------------------
	}
}
